home *** CD-ROM | disk | FTP | other *** search
/ Aminet 6 / Aminet 6 - June 1995.iso / Aminet / dev / src / adoc_src.lha / adoc-0.17 / libfun.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-03-20  |  8.8 KB  |  495 lines

  1. /*                                                               -*- C -*-
  2.  *  LIBFUN.C
  3.  *
  4.  *  (c)Copyright 1995 by Tobias Ferber,  All Rights Reserved
  5.  *
  6.  *  This file is part of ADOC.
  7.  *
  8.  *  ADOC is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published
  10.  *  by the Free Software Foundation; either version 1 of the License,
  11.  *  or (at your option) any later version.
  12.  *
  13.  *  ADOC is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with this program; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23. /* $VER: $Id: libfun.c,v 1.7 1995/03/20 18:44:15 tf Exp $ */
  24.  
  25. #include <ctype.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <stdio.h>
  29.  
  30. #include "libfun.h"
  31.  
  32. /* strexpand.c */
  33. extern char *strexpand(char *, char **);
  34.  
  35. /* minimum #of chars added to funsec.data with each realloc() */
  36. #define SECMINSIZE 1024
  37.  
  38. /* list of sections in a function description */
  39.  
  40. typedef struct funsec
  41. {
  42.   struct funsec *succ, *pred;
  43.   char *name;          /* section title keyword */
  44.   struct {
  45.     char *text;        /* section text */
  46.     size_t len;        /* strlen(text) */
  47.     size_t size;       /* #of chars allocated for text */
  48.   } data;
  49.  
  50. } funsec_t;
  51.  
  52.  
  53. /* library function nodes */
  54.  
  55. typedef struct libfun
  56. {
  57.   struct libfun *succ, *pred;
  58.   char *name;          /* name of the function: `library/function' */
  59.   struct funsec *sec;  /* list of sections in the function description */
  60.  
  61. } libfun_t;
  62.  
  63.  
  64. /* variables */
  65.  
  66. static libfun_t *funlist  = (libfun_t *)0;  /* list of all functions */
  67. static libfun_t *funstack = (libfun_t *)0;  /* function on the stack */
  68. static libfun_t *thisfun  = (libfun_t *)0;  /* the current function (the one constructed last) */
  69. static funsec_t *thissec  = (funsec_t *)0;  /* the current section in the current function */
  70.  
  71. char *pushfun(void) { char *result= funstack ? funstack->name : (char *)0; funstack = thisfun;  return result; }
  72. char *popfun(void)  { char *result= funstack ? funstack->name : (char *)0; thisfun  = funstack; return result; }
  73.  
  74. /**/
  75.  
  76. static libfun_t *libfun_head(libfun_t *lf) { return (lf && lf->pred) ? libfun_head(lf->pred) : lf; }
  77. static libfun_t *libfun_tail(libfun_t *lf) { return (lf && lf->succ) ? libfun_tail(lf->succ) : lf; }
  78.  
  79. static funsec_t *funsec_head(funsec_t *fs) { return (fs && fs->pred) ? funsec_head(fs->pred) : fs; }
  80. static funsec_t *funsec_tail(funsec_t *fs) { return (fs && fs->succ) ? funsec_tail(fs->succ) : fs; }
  81.  
  82. /*
  83. **  NEWFUN
  84. */
  85.  
  86. static libfun_t *libfun_new(char *fun)
  87. {
  88.   libfun_t *lf= (libfun_t *)0;
  89.  
  90.   if(fun)
  91.   {
  92.     lf= (libfun_t *)malloc( sizeof(libfun_t) );
  93.  
  94.     if(lf)
  95.     {
  96.       lf->name= strdup(fun);
  97.  
  98.       if(lf->name)
  99.       {
  100.         lf->succ =
  101.         lf->pred = (libfun_t *)0;
  102.         lf->sec  = (funsec_t *)0;
  103.       }
  104.       else
  105.       {
  106.         free(lf);
  107.         lf= (libfun_t *)0;
  108.       }
  109.     }
  110.   }
  111.  
  112.   return lf;
  113. }
  114.  
  115. /**/
  116.  
  117. int newfun(char *fun)
  118. {
  119.   libfun_t *new= libfun_new(fun);
  120.  
  121.   if(new)
  122.   {
  123.     libfun_t *lf= libfun_tail(funlist);
  124.  
  125.     if(lf)
  126.     {
  127.       lf->succ= new;
  128.       new->pred= lf;
  129.     }
  130.     else funlist= new;
  131.   }
  132.  
  133.   thisfun= new;
  134.   thissec= new->sec;
  135.  
  136.   return new ? 0:1;
  137. }
  138.  
  139. /*
  140. **  FUNSORT
  141. */
  142.  
  143. static int funbubble(libfun_t *a)
  144. {
  145.   int result= 0;
  146.  
  147.   /* perform a recursive bubble-sort on `a' and it's successors
  148.      return the #of bubbles */
  149.  
  150.   if(a && a->succ)
  151.   {
  152.     libfun_t *b= a->succ;
  153.  
  154.     if( strcmp(a->name, b->name) > 0 )
  155.     {
  156.       if( (b->pred= a->pred) )
  157.         b->pred->succ= b;
  158.  
  159.       if( (a->succ= b->succ) )
  160.         a->succ->pred= a;
  161.  
  162.       b->succ= a;
  163.       a->pred= b;
  164.  
  165.       ++result;
  166.     }
  167.  
  168.     result += funbubble(b);
  169.   }
  170.  
  171.   return result;
  172. }
  173.  
  174. /**/
  175.  
  176. void funsort(void)
  177. {
  178.   /* as long as there are bubbles... */
  179.   while( funbubble(libfun_head(funlist)) );
  180.  
  181.   /* sorting might have made another libfun_t the head of funlist */
  182.   funlist= libfun_head(funlist);
  183.  
  184.   for(thisfun= funlist; thisfun; thisfun= thisfun->succ)
  185.   {
  186.     /* make sure that thisfun->sec is the head of the sections */
  187.     thisfun->sec= funsec_head(thisfun->sec);
  188.   }
  189.  
  190.   thisfun= (libfun_t *)0;
  191.   thissec= (funsec_t *)0;
  192. }
  193.  
  194.  
  195. /*
  196. **  FUNEXPAND
  197. */
  198.  
  199. int funexpand(char **macros)
  200. {
  201.   int err= 0;
  202.  
  203.   libfun_t *lf;
  204.   funsec_t *fs;
  205.  
  206.   for(lf= libfun_head(funlist); lf && (err==0); lf= lf->succ)
  207.   {
  208.     for(fs= funsec_head(lf->sec); fs && (err==0); fs= fs->succ)
  209.     {
  210.       if( fs->data.text )
  211.       {
  212.         char *x= strexpand(fs->data.text, macros);
  213.  
  214.         if(x)
  215.         {
  216.           free(fs->data.text);
  217.           fs->data.text= x;
  218.         }
  219.         else err= 1;
  220.       }
  221.     }
  222.   }
  223.  
  224.   return err;
  225. }
  226.  
  227.  
  228. /*
  229. **  NEWSEC
  230. */
  231.  
  232. static funsec_t *funsec_new(char *title)
  233. {
  234.   funsec_t *fs= (funsec_t *)malloc( sizeof(funsec_t) );
  235.  
  236.   if(fs)
  237.   {
  238.     fs->name= (title) ? strdup(title) : (char *)0;
  239.  
  240.     if(title && !fs->name)
  241.     {
  242.       free(fs);
  243.       fs= (funsec_t *)0;
  244.     }
  245.  
  246.     else
  247.     {
  248.       fs->succ =
  249.       fs->pred = (funsec_t *)0;
  250.  
  251.       fs->data.text = (char *)0;
  252.       fs->data.len  =
  253.       fs->data.size = 0;
  254.     }
  255.   }
  256.  
  257.   return fs;
  258. }
  259.  
  260.  
  261. int newsec(char *title)
  262. {
  263.   int err= 0;
  264.  
  265.   if(thisfun)
  266.   {
  267.     funsec_t *new= funsec_new(title);
  268.  
  269.     if(new)
  270.     {
  271.       funsec_t *fs= funsec_tail(thisfun->sec);
  272.  
  273.       if(fs)
  274.       {
  275.         fs->succ= new;
  276.         new->pred= fs;
  277.       }
  278.       else thisfun->sec= new;
  279.     }
  280.     else err= 2;
  281.  
  282.     thissec= new;
  283.   }
  284.   else err= 1;
  285.  
  286.   return err;
  287. }
  288.  
  289. /*
  290. **  ADDTEXT
  291. */
  292.  
  293. int addtext(char *text)
  294. {
  295.   int err= 0;
  296.  
  297.   if(thissec)
  298.   {
  299.     if(text)
  300.     {
  301.       /* get the minimum needed size of the text block */
  302.       size_t len= thissec->data.len + 1 + strlen(text) + 1;  /* '\n' + '\0' */
  303.  
  304.       /* see if we have enough room for '\n' and text */
  305.       if(len >= thissec->data.size)
  306.       {
  307.         /* resize the text buffer to the needed size + SECMINSIZE chars */
  308.         char *old= thissec->data.text;
  309.         char *new= (char *)realloc(old, (SECMINSIZE + len) * sizeof(char) );
  310.  
  311.         if(new)
  312.         {
  313.           thissec->data.text = new;
  314.           thissec->data.size = SECMINSIZE + len;
  315.  
  316.           if(!old)
  317.             *new= '\0';
  318.         }
  319.         else /* !new */
  320.         {
  321.           free(thissec->data.text);
  322.           thissec->data.text = (char *)0;
  323.           thissec->data.len  =
  324.           thissec->data.size = 0;
  325.           err= 1;
  326.         }
  327.       }
  328.  
  329.       /* append the new `text' portion to the section text */
  330.       if(thissec->data.text)
  331.       {
  332.         if(*thissec->data.text)
  333.           strcat(thissec->data.text,"\n");
  334.  
  335.         if(*text)
  336.           strcat(thissec->data.text,text);
  337.  
  338.         thissec->data.len= strlen(thissec->data.text);
  339.       }
  340.  
  341.     }
  342.     /* else: no error */
  343.   }
  344.   else err= -1;
  345.  
  346.   return err;
  347. }
  348.  
  349.  
  350. /*
  351. **  GETxxx
  352. */
  353.  
  354. char *getfun(char *name)
  355. {
  356.   libfun_t *lf= (libfun_t *)0;
  357.  
  358.   if(name)
  359.   {
  360.     for(lf= libfun_head(funlist); (lf && strcmp(lf->name, name)); lf= lf->succ) 
  361.       ;
  362.   }
  363.   else lf= thisfun;
  364.  
  365.   return lf ? lf->name : (char *)0;
  366. }
  367.  
  368.  
  369.  
  370.  
  371. char *getsec(char *name)
  372. {
  373.   funsec_t *fs= (funsec_t *)0;
  374.  
  375.   if(name)
  376.   {
  377.     if(thisfun)
  378.     {
  379.       for(fs= funsec_head(thisfun->sec); (fs && strcmp(fs->name, name)); fs= fs->succ)
  380.         ;
  381.     }
  382.   }
  383.   else fs= thissec;
  384.  
  385.   return fs ? fs->data.text : (char *)0;
  386. }
  387.  
  388.  
  389. /*
  390. **  STEPxxx
  391. */
  392.  
  393.  
  394. char *stepfun(int trigger)
  395. {
  396.   char *result= (char *)0;
  397.  
  398.   if(trigger > 0)
  399.   {
  400.     for(; thisfun && (trigger > 0); trigger--)
  401.       thisfun= thisfun->succ;
  402.   }
  403.   else if(trigger < 0)
  404.   {
  405.     for(; thisfun && (trigger < 0); trigger++)
  406.       thisfun= thisfun->pred;
  407.   }
  408.   else /* trigger == 0 */
  409.     thisfun= libfun_head(funlist);
  410.  
  411.   if(thisfun)
  412.   {
  413.     thissec= funsec_head(thisfun->sec);
  414.     result= thisfun->name;
  415.   }
  416.   else thissec= (funsec_t *)0;
  417.  
  418.   return result;
  419. }
  420.  
  421.  
  422.  
  423. char *stepsec(int trigger)
  424. {
  425.   char *result= (char *)0;
  426.  
  427.   if(trigger > 0)
  428.   {
  429.     for(; thissec && (trigger > 0); trigger--)
  430.       thissec= thissec->succ;
  431.   }
  432.   else if(trigger < 0)
  433.   {
  434.     for(; thissec && (trigger < 0); trigger++)
  435.       thissec= thissec->pred;
  436.   }
  437.   else /* trigger == 0 */
  438.   {
  439.     if(thisfun)
  440.       thissec= funsec_head(thisfun->sec);
  441.  
  442.     else
  443.       thissec= (funsec_t *)0;
  444.   }
  445.  
  446.   if(thissec)
  447.     result= thissec->name;
  448.  
  449.   return result;
  450. }
  451.  
  452.  
  453. /*
  454. **  FREEFUN
  455. */
  456.  
  457. static funsec_t *funsec_dispose(funsec_t *fs)
  458. {
  459.   if(fs)
  460.   {
  461.     fs->succ= funsec_dispose(fs->succ);
  462.  
  463.     if(fs->name)
  464.       free(fs->name);
  465.  
  466.     if(fs->data.text)
  467.       free(fs->data.text);
  468.   }
  469.  
  470.   return (funsec_t *)0;
  471. }
  472.  
  473. static libfun_t *libfun_dispose(libfun_t *lf)
  474. {
  475.   if(lf)
  476.   {
  477.     lf->succ= libfun_dispose(lf->succ);
  478.  
  479.     if(lf->name)
  480.       free(lf->name);
  481.  
  482.     lf->sec= funsec_dispose( funsec_head(lf->sec) );
  483.  
  484.     free(lf);
  485.   }
  486.  
  487.   return (libfun_t *)0;
  488. }
  489.  
  490. void funfree(void)
  491. {
  492.   funlist= thisfun= libfun_dispose( libfun_head(funlist) );
  493.   thissec= (funsec_t *)0;
  494. }
  495.